package com.qiaoba.module.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.qiaoba.common.base.constant.BaseConstant;
import com.qiaoba.common.base.constant.ConfigConstant;
import com.qiaoba.common.base.exception.ServiceException;
import com.qiaoba.module.system.converter.SysConfigConverter;
import com.qiaoba.module.system.entity.SysConfig;
import com.qiaoba.module.system.entity.dto.SysConfigDTO;
import com.qiaoba.module.system.entity.param.SysConfigParam;
import com.qiaoba.module.system.mapper.SysConfigMapper;
import com.qiaoba.module.system.service.SysConfigService;
import com.qiaoba.nosql.redis.service.RedisService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 参数配置 服务层实现
 *
 * @author ailanyin
 * @date 2023-09-09 17:00:30
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SysConfigServiceImpl implements SysConfigService {

    private final RedisService redisService;
    private final SysConfigMapper sysConfigMapper;

    @Override
    public SysConfig selectById(String configId, boolean allowNull) {
        SysConfig sysConfig = sysConfigMapper.selectById(configId);
        if (!allowNull && Objects.isNull(sysConfig)) {
            throw new ServiceException(StrUtil.format("找不到ID为{}的参数配置", configId));
        }
        return sysConfig;
    }

    @Override
    public List<SysConfig> selectList(SysConfigParam param) {
        return sysConfigMapper.selectList(SysConfigConverter.param2Wrapper(param));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(List<String> ids) {
        log.info("执行参数配置-删除,入参: {}", ids);
        List<SysConfig> configs = sysConfigMapper.selectByIds(ids);
        List<String> delKeys = new ArrayList<>();
        for (SysConfig sysConfig : configs) {
            if (BaseConstant.YES.equals(sysConfig.getConfigType())) {
                throw new ServiceException(StrUtil.format("系统内置【{}】不允许删除", sysConfig.getConfigKey()));
            }
            delKeys.add(ConfigConstant.SYS_CONFIG_KEY_PREFIX + sysConfig.getConfigKey());
        }
        redisService.del(delKeys);
        return sysConfigMapper.deleteBatchIds(ids);
    }

    @Override
    public void resetCache() {
        List<SysConfig> sysConfigList = selectList(new SysConfigParam());
        for (SysConfig sysConfig : sysConfigList) {
            redisService.set(ConfigConstant.SYS_CONFIG_KEY_PREFIX + sysConfig.getConfigKey(), sysConfig.getConfigValue());
            log.info("已导入参数配置, Key: {}, Value: {}", sysConfig.getConfigKey(), sysConfig.getConfigValue());
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(SysConfigDTO dto) {
        log.info("执行参数配置-新增,入参: {}", dto);
        // 校验
        checkConfigNameUnique(dto.getConfigId(), dto.getConfigName());
        checkConfigKeyUnique(dto.getConfigId(), dto.getConfigKey());

        SysConfig sysConfig = SysConfigConverter.dto2Entity(dto);
        // 入库
        int result = sysConfigMapper.insert(sysConfig);
        // 入缓存
        if (result > 0) {
            redisService.set(ConfigConstant.SYS_CONFIG_KEY_PREFIX + sysConfig.getConfigKey(), sysConfig.getConfigValue());
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(SysConfigDTO dto) {
        log.info("执行参数配置-修改,入参: {}", dto);
        // 校验
        checkConfigNameUnique(dto.getConfigId(), dto.getConfigName());
        checkConfigKeyUnique(dto.getConfigId(), dto.getConfigKey());
        // 禁止修改key
        SysConfig sysConfig = SysConfigConverter.dto2Entity(dto);
        sysConfig.setConfigKey(null);
        // 入库
        int result = sysConfigMapper.updateById(sysConfig);
        // 入缓存
        if (result > 0) {
            redisService.set(ConfigConstant.SYS_CONFIG_KEY_PREFIX + dto.getConfigKey(), sysConfig.getConfigValue());
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteById(String configId) {
        log.info("执行参数配置-删除,入参: {}", configId);
        SysConfig sysConfig = selectById(configId, false);
        // 系统内置不允许删除
        if (ConfigConstant.CONFIG_TYPE_YES.equals(sysConfig.getConfigType())) {
            throw new ServiceException(StrUtil.format("系统内置【{}】不允许删除", sysConfig.getConfigKey()));
        }
        // 删库
        int result = sysConfigMapper.deleteById(configId);
        // 删缓存
        if (result > 0) {
            redisService.del(ConfigConstant.SYS_CONFIG_KEY_PREFIX + sysConfig.getConfigKey());
        }
        return result;
    }

    @Override
    public String selectConfigByKey(String configKey) {
        return redisService.getObject(ConfigConstant.SYS_CONFIG_KEY_PREFIX + configKey, String.class);
    }

    private void checkConfigNameUnique(String configId, String configName) {
        if (StrUtil.isNotBlank(sysConfigMapper.checkConfigNameUnique(configId, configName))) {
            throw new ServiceException(StrUtil.format("参数名称【{}】已存在", configName));
        }
    }

    private void checkConfigKeyUnique(String configId, String configKey) {
        if (StrUtil.isNotBlank(sysConfigMapper.checkConfigKeyUnique(configId, configKey))) {
            throw new ServiceException(StrUtil.format("参数键值【{}】已存在", configKey));
        }
    }

}
